package com.yutian.springbootwebflux.controller;

import com.yutian.springbootwebflux.exception.ResourceNotFoundException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Api(tags="用户管理")
@RestController
@RequestMapping("/user")
public class UserController {
    private final Map<Long, User> data = new ConcurrentHashMap<>();

    // 定义在某个控制类内,所定义的异常处理控制器方法仅仅覆盖当前控制器类内各个方法所发生的这类异常。但推荐定义全局异常处理类
    /*@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Resource not found")
    @ExceptionHandler(ResourceNotFoundException.class)
    public void notFound() {
    }*/

    @ApiOperation("保存用户")
    @PostMapping("/save")
    public  Mono<User> createOrUpdate(@RequestBody User user) {
        this.data.put(user.getId(), user);
        return Mono.just(user);
    }

    @ApiOperation("用户详情")
    @GetMapping("/{userId}")
    public Mono<User> getUser(@PathVariable Long userId) {
        return Mono.justOrEmpty(this.data.get(userId))
                .switchIfEmpty(Mono.error(new ResourceNotFoundException("user.not.found")));
    }

    @ApiOperation("用户列表")
    @GetMapping("/list")
    public Flux<User> listUser(String userIds) {
        // RequestParamMethodArgumentResolver does not support reactive type wrapper: reactor.core.publisher.Flux<java.lang.String>
        Flux<String> ids = Flux.just(userIds.split(","));
        return ids.flatMap(id -> Mono.justOrEmpty(this.data.get(Long.valueOf(id))));
    }

    @ApiOperation("删除用户")
    @DeleteMapping("/{userId}")
    public Mono<User> deleteUser(@PathVariable Long userId) {
        return Mono.justOrEmpty(this.data.remove(userId));
    }

}